home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / MacTCP / MacTCP Developer Tools / HyperCard MacTCP Toolkit 1.0 / Source Code ƒ / TCPNameToAddr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-21  |  6.4 KB  |  203 lines  |  [TEXT/MPS ]

  1. /*
  2.     TCPNameToAddr(hostName,timeOut,hostFile) -- Return a list of alternative addresses for the host
  3.         name specified. If the name can't be resolved locally, go ask a name server. If it can't be resolved
  4.         within timeOut ticks, give up. The hostFile parameter gives the file name of a local name table
  5.         file. The last two parameters are optional. timeOut defaults to 1800. hostFile defaults to none.
  6.  
  7.     To compile and link this file using Macintosh Programmer's Workshop,
  8.  
  9.         c -b TCPNameToAddr.p
  10.         link -m ENTRYPOINT -o "TCP XCMD Example" -rt XFCN=7870 -sn Main=TCPNameToAddr ∂
  11.             TCPNameToAddr.c.o "{Libraries}HyperXLib.o" "{Libraries}Interface.o" "{CLibraries}CInterface.o" ∂
  12.             "{CLibraries}StdCLib.o"
  13.  
  14.     © Copyright 1989 by Apple Computer, Inc.
  15.  
  16.     Initial coding 3/89 by Harry R. Chesley.
  17. */
  18.  
  19. #include <OSUtils.h>
  20. #include <Errors.h>
  21. #include <Files.h>
  22. #include <Resources.h>
  23. #include <Memory.h>
  24. #include <Events.h>
  25. #include <HyperXCmd.h>
  26. #include <String.h>
  27. #include "MacTCPCommonTypes.h"
  28.  
  29. /* DNR resource function IDs. */
  30. #define OPENRESOLVER 1
  31. #define CLOSERESOLVER 2
  32. #define STRTOADDR 3
  33. #define    ADDRTOSTR 4
  34. #define    ENUMCACHE 5
  35. #define ADDRTONAME 6
  36.  
  37. /* Default time-out. */
  38. #define DEFAULTTICK 3600
  39. /* Minimum time-out (to fix bug in MacTCP). */
  40. #define MINTICK 2400
  41.  
  42. /* Number of addresses returned by DNR. */
  43. #define NUM_ALT_ADDRS    4
  44.  
  45. /* DNR return structure. */
  46. typedef struct hostInfo {
  47.     int    rtnCode;                                            /* Result code. */
  48.     char cname[255];                                        /* Standard name. */
  49.     unsigned long addr[NUM_ALT_ADDRS];        /* Addresses. */
  50. };
  51.  
  52. typedef OSErr (*OSErrProcPtr)();
  53.  
  54. pascal void EntryPoint(XCmdPtr paramPtr)
  55.  
  56. {
  57.     Handle codeHndl;                    /* DNR code resource handle. */
  58.     OSErrProcPtr dnr;                /* Pointer to code resource. */
  59.     SysEnvRec info;                    /* System info record (to find the system volume). */
  60.     HParamBlockRec fi;                /* Parameter block (to find the MacTCP file). */
  61.     Str255 filename;                    /* File name (for MacTCP file search). */
  62.     char str[256];                        /* Scratch string. */
  63.     char resultStr[256];            /* Result string. */
  64.     Handle resultHand;                /* Result handle. */
  65.     short refnum;                        /* Resource file refnum. */
  66.     OSErr rc;                                /* Result code return. */
  67.     struct hostInfo rtnStruct;        /* Answer from DNR. */
  68.     struct hostInfo cacheFltRtn;    /* Place to return the answer if there's a cache fault. */
  69.     long lastTick;                        /* When to time-out. */
  70.     int i;
  71.     pascal void resultProc();
  72.     void errAbort();
  73.  
  74.     /* Check that we've got the right number of parameters. */
  75.     if ((paramPtr->paramCount < 1) || (paramPtr->paramCount > 3)) {
  76.         errAbort(paramPtr,"§§§ parameter count must be 1, 2, or 3 §§§");
  77.         return;
  78.     };
  79.  
  80.     /* Get the system volume. */
  81.     SysEnvirons(1, &info);
  82.  
  83.     /* Prepare to scan for the MacTCP file (where we'll find the DNR code resource). */
  84.     fi.fileParam.ioCompletion = nil;
  85.     fi.fileParam.ioNamePtr = &filename;
  86.     fi.fileParam.ioVRefNum = info.sysVRefNum;
  87.     fi.fileParam.ioDirID = 0;
  88.     fi.fileParam.ioFDirIndex = 1;
  89.     refnum = -1;
  90.     /* Scan for MacTCP file. */
  91.     while (PBHGetFInfo(&fi, false) == noErr) {
  92.         /* scan system folder for driver resource files of specific type & creator */
  93.         if (fi.fileParam.ioFlFndrInfo.fdType == 'cdev' &&
  94.             fi.fileParam.ioFlFndrInfo.fdCreator == 'mtcp') {
  95.             /* Found the MacTCP driver file. */
  96.             SetVol(nil,fi.fileParam.ioVRefNum);
  97.             refnum = OpenResFile(&filename);
  98.             break;
  99.         };
  100.         /* Check next file in system folder. */
  101.         fi.fileParam.ioFDirIndex++;
  102.         fi.fileParam.ioDirID = 0;
  103.     };
  104.  
  105.     /* Ignore failures since the resource may have been installed in the 
  106.        System file if running on a Mac 512Ke. */
  107.        
  108.     /* Load in the DNR resource package. */
  109.     codeHndl = GetIndResource('dnrp', 1);
  110.     if (codeHndl == nil) {
  111.         if (refnum != -1) CloseResFile(refnum);
  112.         errAbort(paramPtr,"§§§ couldn't open resource §§§");
  113.         return;
  114.     };
  115.     DetachResource(codeHndl);
  116.     if (refnum != -1) CloseResFile(refnum);
  117.         
  118.     /* Lock the DNR resource so it cannot be relocated while opened. */
  119.     HLock(codeHndl);
  120.     dnr = (OSErrProcPtr) *codeHndl;
  121.     
  122.     /* Call open resolver. */
  123.     if ((paramPtr->paramCount < 3) || (paramPtr->params[2] == nil)) *str = 0;
  124.     else strcpy(str,*(paramPtr->params[2])); 
  125.     rc = (*dnr)(OPENRESOLVER, str);
  126.     if (rc != noErr) {
  127.         /* Problem with open resolver, flush it. */
  128.         HUnlock(codeHndl);
  129.         DisposHandle(codeHndl);
  130.         errAbort(paramPtr,"§§§ domain name resolver failed §§§");
  131.         return;
  132.     };
  133.  
  134.     /* Get the address. */
  135.     if (paramPtr->params[0] == nil) *str = 0;
  136.     else strcpy(str,*(paramPtr->params[0])); 
  137.     cacheFltRtn.rtnCode = 1;
  138.     rc = (*dnr)(STRTOADDR, str, &rtnStruct, resultProc, &cacheFltRtn);
  139.  
  140.     /* If we couldn't get it right away, wait for it. */
  141.     if (rc == cacheFault) {
  142.         if ((paramPtr->paramCount < 2) || (paramPtr->params[1] == nil)) lastTick = TickCount() + DEFAULTTICK;
  143.         else if (**paramPtr->params[1] == 0) lastTick = TickCount() + DEFAULTTICK;
  144.         else {
  145.             ZeroToPas(paramPtr,*(paramPtr->params[1]),str);
  146.             if ((lastTick = StrToNum(paramPtr,str)) > MINTICK) lastTick = MINTICK;
  147.             lastTick = lastTick + TickCount();
  148.         };
  149.         while ((TickCount() < lastTick) && (cacheFltRtn.rtnCode > 0));
  150.         rtnStruct = cacheFltRtn;
  151.     } else rtnStruct.rtnCode = rc;
  152.  
  153.     /* Check if we got it OK or not. */
  154.     if (rtnStruct.rtnCode == noErr) {
  155.         /* We did, so build the result string. */
  156.         *resultStr = 0;
  157.         for (i = 0; i < NUM_ALT_ADDRS; i++) {
  158.             if (rtnStruct.addr[i] == 0) break;
  159.             if (i > 0) strcat(resultStr,",");
  160.             NumToStr(paramPtr,rtnStruct.addr[i],str);
  161.             p2cstr(str);
  162.             strcat(resultStr,str);
  163.         };
  164.         /* Make the handle to return. */
  165.         resultHand = NewHandle((long) strlen(resultStr)+1);
  166.         if (resultHand != nil) {
  167.             strcpy(*resultHand,resultStr);
  168.             paramPtr->returnValue = resultHand;
  169.         } else errAbort(paramPtr,"§§§ couldn't make result string §§§");
  170.     } else if (rtnStruct.rtnCode == 1) errAbort("§§§ time-out §§§");
  171.     else errAbort(paramPtr,"§§§ couldn't get address §§§");
  172.  
  173.     /* Call close resolver. */
  174.     (void) (*dnr)(CLOSERESOLVER);
  175.  
  176.     /* Release the DNR resource package. */
  177.     HUnlock(codeHndl);
  178.     DisposHandle(codeHndl);
  179. }
  180.  
  181. /* Async routine called when name is found from name server. We just copy the result
  182.     and let the main loop process it. */
  183.     
  184. pascal void resultProc(struct hostInfo *hostInfoPtr, struct hostInfo *userDataPtr)
  185.  
  186. {
  187.     *userDataPtr = *hostInfoPtr;
  188. }
  189.  
  190. /* Error handling: return the string as a result. */
  191.  
  192. void errAbort(XCmdPtr paramPtr, char *str)
  193.  
  194. {
  195.     Handle  nuHndl;
  196.  
  197.     /* Allocate space for an error message, copy the string into it, and return the handle to HyperCard. */
  198.     nuHndl = NewHandle((long)(strlen(str)+1));
  199.     if (nuHndl == nil) return;
  200.     strcpy((char *)*nuHndl,str);
  201.     paramPtr->returnValue = nuHndl;
  202. }
  203.